Skip to content

feat(react-charts): vega lite schema support#35546

Merged
AtishayMsft merged 72 commits intomicrosoft:masterfrom
AtishayMsft:usr/atisjai/vegaLiteFluent
Mar 2, 2026
Merged

feat(react-charts): vega lite schema support#35546
AtishayMsft merged 72 commits intomicrosoft:masterfrom
AtishayMsft:usr/atisjai/vegaLiteFluent

Conversation

@AtishayMsft
Copy link
Contributor

@AtishayMsft AtishayMsft commented Dec 6, 2025

Previous Behavior

New Behavior

Summary

Adds a new VegaDeclarativeChart component that renders Vega-Lite specifications using Fluent UI chart components. This is a companion to the existing Plotly-based DeclarativeChart, enabling a second declarative grammar for data visualization.

The component transforms Vega-Lite JSON specs into the appropriate Fluent UI chart type (line, bar, area, scatter, donut, heatmap, polar, etc.) and renders them with full interactivity including legends, tooltips, and theme support.

New Files

File Purpose
VegaDeclarativeChart.tsx Main component — chart type detection, routing, concat layout support, shared legend for multi-chart layouts
VegaLiteSchemaAdapter.ts Transforms Vega-Lite specs into Fluent chart props (12 chart type transformers)
VegaLiteTypes.ts TypeScript interfaces for Vega-Lite spec structure (marks, encodings, scales, axes, etc.)
VegaLiteColorAdapter.ts Color scheme mapping (category10, tableau10, etc.) and persistent color assignment via colorMap
VegaDeclarativeChartHooks.ts Shared hooks — useIsDarkTheme() and useColorMapping()
VegaDeclarativeChartDefault.stories.tsx Storybook story with 25 inline schemas + GitHub-loaded schema browser
VegaDeclarativeChart.test.tsx 40 component-level tests (rendering, snapshots, chart type detection)
VegaLiteSchemaAdapterUT.test.tsx 54 adapter unit tests (transformers, validation, edge cases)

Supported Chart Types

  • Line — temporal, quantitative, and ordinal x-axes; multi-series with color encoding; interpolation mapping
  • Area — stacked area charts with color encoding
  • Vertical Bar — categorical and quantitative x-axes; numeric x values converted to categorical strings
  • Stacked Bar — color-encoded stacking; combo bar+line layered specs; aggregate support (count/sum/mean)
  • Grouped Bar — xOffset encoding detection
  • Horizontal Bar — nominal/ordinal y-axis detection; aggregate support
  • Scatter — point/circle/square marks; size and color encoding
  • Donut/Pie — arc marks with theta encoding; innerRadius for donut vs pie
  • Heatmap — rect marks with quantitative color; complete grid generation (fills missing cells with 0); named color schemes (blues, viridis, etc.)
  • Histogram — binned x-axis with configurable bin count; non-count aggregates (max/mean/sum)
  • Polar — theta+radius encoding for radial charts
  • Combo — layered bar+line specs rendered via stacked bar with line overlays

Key Features

  • Auto-correction of encoding types — quantitative fields with string data are auto-corrected to nominal before chart type routing, matching Plotly adapter behavior
  • Aggregate supportcount, sum, mean, min, max aggregations on bar charts (vertical, horizontal, stacked)
  • hconcat/vconcat layouts — multiple charts in grid layout with shared legend rendered outside the grid; legend selection propagates to all sub-charts
  • Fold transformtransform: [{fold: [...]}] for reshaping wide data to long format
  • Color persistencecolorMap ref maintains consistent color assignments across re-renders
  • Title extraction — supports both encoding.y.title (shorthand) and encoding.y.axis.title (explicit)
  • Dark theme — automatic theme detection via useIsDarkTheme hook
  • Ordinal x-axis — maps categorical strings to sequential numeric indices with tick labels

API Surface

// New exports from @fluentui/react-charts
export const VegaDeclarativeChart: React.ForwardRefExoticComponent<VegaDeclarativeChartProps>;

export interface VegaDeclarativeChartProps {
  chartSchema: VegaSchema;
  className?: string;
  style?: React.CSSProperties;
  onSchemaChange?: (newSchema: VegaSchema) => void;
}

export interface VegaSchema {
  vegaLiteSpec: VegaLiteSpec;
  selectedLegends?: string[];
}

export type VegaLiteSpec = any; // Accepts any valid Vega-Lite JSON

Test Plan

  • 94 unit tests pass (40 component + 54 adapter)
  • 29 snapshot tests pass
  • tsc --noEmit clean for both tsconfig.lib.json and tsconfig.spec.json
  • nx format:check passes
  • No changes to existing DeclarativeChart (Plotly adapter) or any other component
  • No new dependencies added to package.json
  • Storybook renders correctly with 25 inline schemas covering all chart types

Related Issue(s)

  • Fixes #

@github-actions
Copy link

github-actions bot commented Dec 6, 2025

📊 Bundle size report

✅ No changes found

@github-actions
Copy link

github-actions bot commented Dec 6, 2025

Pull request demo site: URL

atisjai and others added 15 commits January 7, 2026 07:41
atisjai and others added 26 commits February 16, 2026 17:29
- Add Playwright e2e spec for batch screenshot testing of vega schemas
- Add unit test spec for VegaDeclarativeChart storybook stories
- Add timeout test spec for debugging blank/error schemas
- Add Playwright config and helper scripts (e2e runner, contact sheets)
- Add code review observations and reported bugs documentation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove overflow:hidden from grid container and cells so legends
are not clipped. minWidth:0 already prevents grid blowout.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Hide legends on all sub-charts and render a single shared legend
below the grid using getVegaLiteLegendsProps + Legends component.
Fixes legend being clipped inside grid cells.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pass multiSelectLegendProps (canSelectMultipleLegends, onChange,
selectedLegends) to the shared Legends component so clicking a
legend item propagates the selection state to all sub-charts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Verifies that hconcat donut charts render a shared legend
outside the grid with correct legend items.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Revert DeclarativeChart.tsx and ChartTable.tsx to master
  (keep DeclarativeChartHooks.ts as shared utility)
- Remove color-schemes and validation-tests example folders
- Remove CODE_REVIEW_OBSERVATIONS.md and ReportedBugs.csv
- Remove E2E_SCREENSHOT_TESTING.md, playwright.config.ts
- Remove stories/scripts/ (e2e.js, create-contact-sheets.mjs)
- Remove e2e spec, unit spec, and timeout-test spec files

These helper scripts and docs will be moved to the
fluentui-charting-contrib repository.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rename to VegaDeclarativeChartHooks.ts and update import.
Keeps DeclarativeChart folder clean of Vega-specific files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add !! to isHConcatSpec/isVConcatSpec for boolean coercion
- Add non-null assertions for spec.hconcat/vconcat after guard
- Cast ChartRenderer props to any (transformer output is dynamic)
- Remove unused yType variable
- Fix rectText possibly undefined with fallback
- Cast color.sort access to Record for missing property
- Cast arc mark comparison to string for type overlap
- Add datum, timeUnit, zero, reverse to type interfaces

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restore Schema.plotlySchema to non-optional (matches reverted
DeclarativeChart.tsx) and remove selectedLegends.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add VegaDeclarativeChart to index.ts barrel export and restore
VegaDeclarativeChart, VegaDeclarativeChartProps, VegaLiteSpec,
VegaSchema entries in react-charts.api.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The tsconfig.spec.json strict mode requires explicit types for spec
objects passed to VegaDeclarativeChart to avoid mark type mismatch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ain type

- Add 'arc' to VegaLiteMark union type
- Add xOffset encoding for grouped bar chart detection
- Add tooltip encoding (any type for flexibility)
- Change scale.domain from tuple to array for variable-length domains

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add non-null assertions for spec.encoding, result.data, and
props.data accesses in test assertions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@AtishayMsft AtishayMsft marked this pull request as ready for review March 2, 2026 03:54
@AtishayMsft AtishayMsft removed the request for review from a team March 2, 2026 03:54
@AtishayMsft AtishayMsft merged commit 26229a9 into microsoft:master Mar 2, 2026
12 checks passed
@AtishayMsft AtishayMsft deleted the usr/atisjai/vegaLiteFluent branch March 2, 2026 04:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants